package org.apache.james.mime4j.io;

import java.io.IOException;
import org.apache.james.mime4j.util.ByteArrayBuffer;

public class MimeBoundaryInputStream extends LineReaderInputStream
{
  private boolean atBoundary;
  private final byte[] boundary;
  private int boundaryLen;
  private BufferedLineReaderInputStream buffer;
  private boolean completed;
  private boolean eof;
  private boolean lastPart;
  private int limit;

  public MimeBoundaryInputStream(BufferedLineReaderInputStream paramBufferedLineReaderInputStream, String paramString)
    throws IOException
  {
    super(paramBufferedLineReaderInputStream);
    if (paramBufferedLineReaderInputStream.capacity() <= paramString.length())
      throw new IllegalArgumentException("Boundary is too long");
    this.buffer = paramBufferedLineReaderInputStream;
    this.eof = false;
    this.limit = -1;
    this.atBoundary = false;
    this.boundaryLen = 0;
    this.lastPart = false;
    this.completed = false;
    this.boundary = new byte[2 + paramString.length()];
    this.boundary[0] = 45;
    this.boundary[1] = 45;
    for (int i = 0; i < paramString.length(); ++i)
    {
      int j = (byte)paramString.charAt(i);
      if ((j == 13) || (j == 10))
        throw new IllegalArgumentException("Boundary may not contain CR or LF");
      this.boundary[(i + 2)] = j;
    }
    fillBuffer();
  }

  private void calculateBoundaryLen()
    throws IOException
  {
    this.boundaryLen = this.boundary.length;
    int i = this.limit - this.buffer.pos();
    if ((i > 0) && (this.buffer.charAt(this.limit - 1) == 10))
    {
      this.boundaryLen = (1 + this.boundaryLen);
      this.limit -= 1;
    }
    if ((i > 1) && (this.buffer.charAt(this.limit - 1) == 13))
    {
      this.boundaryLen = (1 + this.boundaryLen);
      this.limit -= 1;
    }
  }

  private boolean endOfStream()
  {
    int i;
    if ((this.eof) || (this.atBoundary))
      i = 1;
    while (true)
    {
      return i;
      i = 0;
    }
  }

  private int fillBuffer()
    throws IOException
  {
    int i;
    int j;
    int k;
    int l;
    if (this.eof)
    {
      l = -1;
      return l;
    }
    if (!(hasData()))
    {
      i = this.buffer.fillBuffer();
      if (i != -1)
        break label114;
      j = 1;
    }
    while (true)
    {
      while (true)
      {
        this.eof = j;
        k = this.buffer.indexOf(this.boundary);
        while (true)
        {
          if ((k <= 0) || (this.buffer.charAt(k - 1) == 10))
            break label119;
          int i1 = k + this.boundary.length;
          k = this.buffer.indexOf(this.boundary, i1, this.buffer.limit() - i1);
        }
        i = 0;
      }
      label114: j = 0;
    }
    if (k != -1)
    {
      label119: this.limit = k;
      this.atBoundary = true;
      calculateBoundaryLen();
    }
    while (true)
    {
      while (true)
      {
        while (true)
          l = i;
        if (!(this.eof))
          break;
        this.limit = this.buffer.limit();
      }
      this.limit = (this.buffer.limit() - 1 + this.boundary.length);
    }
  }

  private boolean hasData()
  {
    int i;
    if ((this.limit > this.buffer.pos()) && (this.limit <= this.buffer.limit()))
      i = 1;
    while (true)
    {
      return i;
      i = 0;
    }
  }

  private void skipBoundary()
    throws IOException
  {
    int i;
    if (!(this.completed))
    {
      this.completed = true;
      this.buffer.skip(this.boundaryLen);
      i = 1;
    }
    while (true)
    {
      int j;
      int k;
      while (true)
      {
        if (this.buffer.length() <= 1)
          break label163;
        j = this.buffer.charAt(this.buffer.pos());
        k = this.buffer.charAt(1 + this.buffer.pos());
        if ((i == 0) || (j != 45) || (k != 45))
          break;
        this.lastPart = true;
        this.buffer.skip(2);
        i = 0;
      }
      if ((j == 13) && (k == 10))
        this.buffer.skip(2);
      label163: 
      do
        while (true)
        {
          while (true)
          {
            return;
            if (j != 10)
              break;
            this.buffer.skip(1);
          }
          this.buffer.skip(1);
        }
      while (this.eof);
      fillBuffer();
    }
  }

  public void close()
    throws IOException
  {
  }

  public boolean eof()
  {
    int i;
    if ((this.eof) && (!(this.buffer.hasBufferedData())))
      i = 1;
    while (true)
    {
      return i;
      i = 0;
    }
  }

  public boolean isLastPart()
  {
    return this.lastPart;
  }

  public boolean markSupported()
  {
    return false;
  }

  public int read()
    throws IOException
  {
    int i;
    if (this.completed)
      i = -1;
    while (true)
    {
      while (true)
      {
        return i;
        if ((!(endOfStream())) || (hasData()))
          break;
        skipBoundary();
        i = -1;
      }
      do
        while (true)
        {
          fillBuffer();
          if (!(hasData()))
            break;
          i = this.buffer.read();
        }
      while (!(endOfStream()));
      skipBoundary();
      i = -1;
    }
  }

  public int read(byte[] paramArrayOfByte, int paramInt1, int paramInt2)
    throws IOException
  {
    int j;
    if (this.completed)
      j = -1;
    while (true)
    {
      while (true)
      {
        while (true)
        {
          return j;
          if ((!(endOfStream())) || (hasData()))
            break;
          skipBoundary();
          j = -1;
        }
        fillBuffer();
        if (hasData())
          break;
        j = read(paramArrayOfByte, paramInt1, paramInt2);
      }
      int i = Math.min(paramInt2, this.limit - this.buffer.pos());
      j = this.buffer.read(paramArrayOfByte, paramInt1, i);
    }
  }

  public int readLine(ByteArrayBuffer paramByteArrayBuffer)
    throws IOException
  {
    int l;
    if (paramByteArrayBuffer == null)
      throw new IllegalArgumentException("Destination buffer may not be null");
    if (this.completed)
      l = -1;
    while (true)
    {
      int i;
      int j;
      int i3;
      while (true)
      {
        while (true)
        {
          return l;
          if ((!(endOfStream())) || (hasData()))
            break;
          skipBoundary();
          l = -1;
        }
        i = 0;
        j = 0;
        int k = 0;
        if (j == 0)
        {
          if (hasData())
            break;
          k = fillBuffer();
          if ((hasData()) || (!(endOfStream())))
            break;
          skipBoundary();
          k = -1;
        }
        if ((i != 0) || (k != -1))
          break label224;
        l = -1;
      }
      int i1 = this.limit - this.buffer.pos();
      int i2 = this.buffer.indexOf(10, this.buffer.pos(), i1);
      if (i2 != -1)
      {
        j = 1;
        i3 = i2 + 1 - this.buffer.pos();
      }
      while (true)
      {
        while (true)
        {
          if (i3 <= 0);
          paramByteArrayBuffer.append(this.buffer.buf(), this.buffer.pos(), i3);
          this.buffer.skip(i3);
          i += i3;
        }
        i3 = i1;
      }
      label224: l = i;
    }
  }

  public String toString()
  {
    StringBuffer localStringBuffer = new StringBuffer("MimeBoundaryInputStream, boundary ");
    for (int i = 0; i < this.boundary.length; ++i)
      localStringBuffer.append((char)this.boundary[i]);
    return localStringBuffer.toString();
  }
}